/* eslint-disable react/no-danger */
import React, {
  createRef,
  useEffect,
  useState,
  useCallback,
  useRef,
} from "react";
import { Button, View } from "@tarojs/components";
import Taro, { useRouter } from "@tarojs/taro";
import classNames from "classnames";
import { debounce } from "debounce";
import {
  AtModal,
  AtModalContent,
  AtTextarea,
  AtFloatLayout,
  AtTabs,
  AtTabsPane,
} from "taro-ui";
import dayjs from "dayjs";
import Hammer from "hammerjs";
import "./index.scss";
import { NavBar } from "../../../src/components/nav-bar";
import { StackAvatars } from "../../../src/components/stack-avatars";
import {
  CheckStatusColor,
  CheckStatusEnum,
  CheckStatusEnumText,
  FileItem,
  IChildren,
  IFileCheckDetail,
  IImg,
  IListing,
  IListingConfirm,
  ISubTaskResponse,
  ITaskAttachment,
  ITaskComment,
  ITaskDetailFieldValues,
  ITaskDetailResponse,
  ITaskPhase,
  TaskCheckStatus,
} from "../../../src/interfaces";
import pageLeft from "../../assets/page-change-left.png";
import pageRight from "../../assets/page-change-right.png";
import { TaskFooter } from "./task-footer";
import { TaskComment } from "./comment";
import closeBlack from "../../assets/close-black.png";
import checkIcon from "../../assets/check-icon.png";
import {
  confirmCheck,
  fetchListingList,
  fetchPhaseList,
  fetchProjectTaskDetail,
  fetchSubTask,
  fetchTaskComment,
  fetchTaskDetail,
  fetchTaskRecord,
  modifyTaskPhase,
} from "../../../src/api";
import { getOssThumbnail, getOssUrl, textColorMap } from "../../../src/utils";
import { PreviewComponent } from "../file-preview/preview-component";
import { matchSuffixType, matchType } from "../../../src/utils/check-file-type";
import { fetchDetailStsToken, fetchStsToken } from "../../../src/api/file-tab";
import { FileImage } from "../../../src/components/img";
import { updateTaskStatus } from "../../../src/api/task-list";
import { isSafari } from "../../../src/utils/check-browser";

// - 任务阶段：61ce9a6acf529c341c7ef8d4
// 任务状态：61ce9a6acf529c341c7ef8d1
// - 开始时间：61ce9a6acf529c341c7ef8c7
// - 截止时间：61ce9a6acf529c341c7ef8c8
// - 内部负责人：61ce9a6acf529c341c7ef8c9
// - 外部负责人：  61ce9a6acf529c341c7ef8ca
// 附件： 61ce9a6acf529c341c7ef8cc
// 评论：61ce9a6acf529c341c7ef8cb
// 确认状态：61ce9a6acf529c341c7ef8c6
// - 所属频道：621de5a57f9852522fc10f88
// - 创建人：61ce9a6acf529c341c7ef8cd
// - 创建时间：61ce9a6acf529c341c7ef8cf
//  完成人：621de5a57f9852522fc10f89
//  - 描述： 61ce9a6acf529c341c7ef8d3
// 完成时间：61ce9a6acf529c341c7ef8d2
// 最后更新人：61ce9a6acf529c341c7ef8ce
// 最后更新时间：61ce9a6acf529c341c7ef8d0

/** 获取子任务树 */
const getTaskChildLength = (task: IChildren) => {
  let count = 0;
  count += task.children.length;
  // task.children.forEach((t) => {
  //   count += getTaskChildLength(t);
  // });
  return count;
};

/** 渲染时间，为0不渲染，大于0，精确到天，小于0，精确到分钟 */
const RenderTime = ({ value }: { value: string }) => {
  if (!value || value === "0" || value === "undefined") return <></>;
  if (+value > 0) {
    return <>{dayjs(+value).format("YYYY/MM/DD")}</>;
  }
  return <>{dayjs(-+value).format("YYYY/MM/DD HH:mm")}</>;
};
/** 获取属性的值 */
const getvalueFromFields = (
  fieldId: string,
  fieldValues?: ITaskDetailFieldValues
) => {
  if (!fieldValues) return;
  const field = fieldValues.data.find((v) => v.fieldId === fieldId);
  return field?.value;
};

/** 任务状态 tag */
const TaskStatusTag = ({
  title,
  color,
  onClick,
}: {
  title: string;
  color: string;
  onClick?: () => void;
}) => {
  return (
    <div
      className={classNames(
        "status "
        // `${complete ? "complete" : "not-complete"}`
      )}
      style={{
        color: textColorMap[color],
        backgroundColor: color,
      }}
      onClick={onClick}
    >
      {title}
    </div>
  );
};

const CheckStatusTag = ({ status }: { status: number }) => {
  return (
    <div className={classNames("status")}>
      <span
        style={{ color: TaskCheckStatus.color[status] }}
        className={`iconfont ${TaskCheckStatus.icon[status]}`}
      ></span>
      {TaskCheckStatus.text[status]}
    </div>
  );
};

/** 任务关键信息-行样式 */
const InfoLine = ({
  name,
  value,
  onClick,
  ellipsis,
}: {
  name: string;
  value: React.ReactNode;
  onClick?: () => void;
  ellipsis?: boolean;
}) => {
  return (
    <div className="information-line">
      <div className="name">{name}</div>
      <div
        className={classNames("value", {
          ellipsis: ellipsis,
        })}
        onClick={onClick}
      >
        {value}
      </div>
    </div>
  );
};
/**自定义字段-单行 */
const CustomInfoLine = ({
  icon,
  name,
  value,
}: {
  icon: string;
  name: string;
  value: React.ReactNode;
}) => {
  return (
    <div className="info one-line">
      <div className="name">
        {/* <img src={icon} />  */}
        <span className={`iconfont ${icon}`}></span>
        <span className="font-bold">{name}</span>
      </div>
      <div className="value">{value}</div>
    </div>
  );
};

/** 自定义多行文本 */
const CustomInfoMultipleText = ({
  name,
  value,
}: {
  name?: string;
  value?: string;
}) => {
  return (
    <div className="info clearfix">
      <div className="name">
        <span className="iconfont icon-wenben small"></span>
        <span className="font-bold">{name}</span>
      </div>
      {value && (
        <div
          className="value"
          dangerouslySetInnerHTML={{
            __html: value,
          }}
        ></div>
      )}
    </div>
  );
};

/**自定义字段-多行 */
const CustomInfoMultipleLine = ({
  icon,
  name,
  value,
}: {
  icon: string;
  name: string;
  value: React.ReactNode;
}) => {
  return (
    <div className="info clearfix">
      <div className="name">
        <span className={`iconfont ${icon}`}></span>
        <span className="ellipsis font-bold">{name}</span>
      </div>
      {value}
    </div>
  );
};

/** 附件 */
const Attachment = ({
  thumbnail,
  name,
  onClick,
  username,
  fieldType,
}: {
  thumbnail?: IImg;
  onClick?: () => void;
  name: string;
  fieldType: number;
  username: string;
}) => {
  const [halfName, ext] = name.split(".");
  const icon =
    matchSuffixType(name, fieldType) || matchType["icon-a-CannotPreview"];
  const ellipsisRef = createRef<HTMLDivElement>();
  useEffect(() => {
    const halfEle = ellipsisRef.current;
    const fullName = ellipsisRef.current?.parentElement;
    const extEle = fullName?.lastElementChild;
    const right = ellipsisRef.current?.parentElement?.parentElement;
    const rowEle =
      ellipsisRef.current?.parentElement?.parentElement?.parentElement;
    const left = rowEle?.firstElementChild;
    if (!rowEle || !left || !right || !extEle || !halfEle) return;
    if (right.clientWidth > rowEle.clientWidth - left.clientWidth) {
      // 需要省略
      const width =
        rowEle.clientWidth -
        left.clientWidth -
        parseInt(getComputedStyle(right).marginLeft) -
        extEle.clientWidth;
      halfEle.style.width = `${width}px`;
    }
  }, []);

  return (
    <div className="attachment" onClick={onClick}>
      <div className="left">
        {thumbnail ? (
          <FileImage src={getOssThumbnail(thumbnail)} icon={icon} />
        ) : (
          <span className={`iconfont ${icon}`}></span>
        )}
      </div>
      <div className="right">
        <div className="name ">
          <div className="half-name ellipsis" ref={ellipsisRef}>
            {halfName}
          </div>
          <div className="ext">{ext ? `.${ext}` : ""}</div>
        </div>
        <div className="username ellipsis">上传人：{username}</div>
      </div>
    </div>
  );
};

/** 确认项 */
const CheckItem = ({
  status,
  sender,
  checker,
  expired,
  confirmType,
  name,
  onClick,
}: {
  name: string;
  status: number;
  sender: string;
  confirmType?: string;
  checker: React.ReactNode;
  expired: string;
  onClick?: () => void;
}) => {
  return (
    <div className="check" onClick={onClick}>
      <div className="title">
        <div className="name ellipsis">{name}</div>
        <CheckStatusTag status={status} />
      </div>
      <div className="check-line">发送人：{sender}</div>
      <div className="check-line">
        确认人：
        {confirmType === "open" && <span className="open">公开</span>}
        {confirmType !== "open" && checker}
      </div>
      <div className="check-line">截止日期：{expired}</div>
    </div>
  );
};

/** 收起展开 */
const Accordion = ({
  className,
  initClose,
  title,
  img,
  children,
}: {
  className?: string;
  initClose?: boolean;
  title: string;
  img: string;
  children?: React.ReactNode;
}) => {
  const [open, setOpen] = useState(true);
  const containerRef = createRef<HTMLDivElement>();
  const titleRef = createRef<HTMLDivElement>();
  const maxHeight = useRef({ maxHeight: "0px" });

  const handleToggle = useCallback(() => {
    setOpen(!open);
    const container = containerRef.current as HTMLDivElement;
    if (!container) return;
    const titleEle = titleRef.current as HTMLDivElement;
    if (open) {
      container.style.maxHeight = getComputedStyle(titleEle).height;
    } else {
      container.style.maxHeight = maxHeight.current.maxHeight;
    }
  }, [open, containerRef, titleRef]);

  useEffect(() => {
    if (!containerRef.current) return;
    // setTimeout(() => {
    const container = containerRef.current as HTMLDivElement;
    maxHeight.current.maxHeight = getComputedStyle(container).height;
    container.style.maxHeight = maxHeight.current.maxHeight;
    // });
    if (initClose) {
      handleToggle();
    }
  }, []);
  return (
    <div
      className={classNames("drop-down-card", className, {
        close: !open,
      })}
      ref={containerRef}
    >
      <div className="title" ref={titleRef}>
        <div className="left">
          {/* <img src={img} alt="" />  */}
          <span className={`iconfont ${img}`}></span>
          <span>{title}</span>
        </div>
        <div
          className={classNames("right", {
            rotate: open,
          })}
          onClick={handleToggle}
        >
          <span className={classNames("iconfont", "icon-down-line")}></span>
        </div>
      </div>
      {children}
    </div>
  );
};

export const StatusLine = ({
  checked,
  onClick,
  color,
  name,
}: {
  name: string;
  checked?: boolean;
  color: string;
  onClick?: () => void;
}) => {
  return (
    <div
      className={classNames("status-line", {
        checked: checked,
      })}
      onClick={onClick}
    >
      <div className="left">
        <div className="icon" style={{ background: color }}></div>
        <div className="name">{name}</div>
      </div>
      <div className="right ">
        <img src={checkIcon} />
      </div>
    </div>
  );
};

/** 页面主题内容，包括默认字段和自定义字段 */
export const TabMainInfo = ({
  detail,
  pageType,
  onStatusClick,
  onPhaseClick,
  onAttachmentClick,
}: {
  detail: ITaskDetailResponse | undefined;
  pageType: number;
  onStatusClick?: () => void;
  onPhaseClick?: () => void;
  onAttachmentClick?: (file: any) => void;
}) => {
  return (
    <>
      <div className="base-info">
        <div className="desc">
          {getvalueFromFields("61ce9a6acf529c341c7ef8c0", detail?.fieldValues)}
        </div>
        <div className="time">
          {
            getvalueFromFields("61ce9a6acf529c341c7ef8cd", detail?.fieldValues)
              ?.nickName
          }
          创建于
          {(() => {
            const value = getvalueFromFields(
              "61ce9a6acf529c341c7ef8cf",
              detail?.fieldValues
            );
            return <RenderTime value={`${value}`} />;
          })()}
        </div>
      </div>
      <div className="information">
        <div className="container">
          <InfoLine
            name="任务状态"
            value={(() => {
              const stateId = detail?.fieldValues.stateId;
              const status = detail?.fieldValues.stateOptions?.find(
                (opt) => opt.id === stateId
              );
              if (!status) return "";
              return (
                <TaskStatusTag
                  title={status.value}
                  color={status.color}
                  onClick={onStatusClick}
                />
              );
            })()}
          />
          <InfoLine
            name="任务阶段"
            onClick={onPhaseClick}
            ellipsis
            value={(() => {
              const value = getvalueFromFields(
                "61ce9a6acf529c341c7ef8d4",
                detail?.fieldValues
              )?.name;
              if (value) return value;
              return (
                <div style={{ visibility: "hidden", minWidth: "50px" }}>无</div>
              );
            })()}
          />
          <div className="information-line channels-line">
            <div className="name">所属频道</div>
            <div className="channels">
              {(() => {
                const tags =
                  getvalueFromFields(
                    "621de5a57f9852522fc10f88",
                    detail?.fieldValues
                  ) || [];
                let ret = [
                  <div className="channel-tag">
                    {detail?.fieldValues.originName}
                  </div>,
                ];
                if (tags && tags.length) {
                  return ret.concat(
                    tags.map((item) => {
                      return <div className="channel-tag">{item.name}</div>;
                    })
                  );
                }
                return ret[0];
              })()}
            </div>
          </div>
          <InfoLine
            name="开始时间"
            value={(() => {
              const value = getvalueFromFields(
                "61ce9a6acf529c341c7ef8c7",
                detail?.fieldValues
              );
              return <RenderTime value={`${value}`} />;
            })()}
          />
          <InfoLine
            name="截止时间"
            value={(() => {
              const value = getvalueFromFields(
                "61ce9a6acf529c341c7ef8c8",
                detail?.fieldValues
              );
              return <RenderTime value={`${value}`} />;
            })()}
          />
          <InfoLine
            name="内部负责人"
            value={(() => {
              const value = getvalueFromFields(
                "61ce9a6acf529c341c7ef8ca",
                detail?.fieldValues
              );
              const imgs = (value || []).map((u) => ({
                src: getOssUrl(u.img || {}),
                text: u.nickName,
              }));
              return (
                <StackAvatars
                  maxLength={5}
                  showCount={imgs.length > 5}
                  imgs={imgs}
                />
              );
            })()}
          />
          <InfoLine
            name="外部负责人"
            value={(() => {
              const value = getvalueFromFields(
                "61ce9a6acf529c341c7ef8c9",
                detail?.fieldValues
              );
              const imgs = (value || []).map((u) => ({
                src: getOssUrl(u.img || {}),
                text: u.nickName,
              }));
              return (
                <StackAvatars
                  maxLength={5}
                  showCount={imgs.length > 5}
                  imgs={imgs}
                />
              );
            })()}
          />
        </div>
      </div>
      {(() => {
        const value = getvalueFromFields(
          "61ce9a6acf529c341c7ef8d3",
          detail?.fieldValues
        );
        return (
          <div
            className={classNames(`description`, {
              empty: !value,
            })}
          >
            <div className={classNames("title")}>
              <span className="iconfont icon-menu-line"></span>
              <span>描述</span>
            </div>
            {value && (
              <div
                id="editor-container"
                className="word desc-editor"
                dangerouslySetInnerHTML={{
                  __html: value,
                }}
              ></div>
            )}
          </div>
        );
      })()}
      <Accordion
        title="自定义字段"
        key={detail?.fields[0]?.viewId}
        img="icon-zidingyi"
        className="more-info"
      >
        {(detail?.fields || [])
          .filter((field) => field.custom)
          .map((field) => {
            const fieldValue = (detail?.fieldValues.data || []).find(
              (f) => f.fieldId === field.fieldId
            ) as any;
            switch (field.fieldType) {
              // 多行文本
              case 1: {
                return (
                  <CustomInfoMultipleText
                    name={field.name}
                    key={field.id as string}
                    value={fieldValue.value}
                  />
                );
              }
              // 数字
              case 2: {
                return (
                  <CustomInfoMultipleLine
                    key={field.id}
                    icon="icon-shuzi"
                    name={field.name}
                    value={
                      fieldValue.value && (
                        <div className="value">{fieldValue.value}</div>
                      )
                    }
                  />
                );
              }
              // 单选
              case 3: {
                const options = field.property.options;
                const option = options.find((o) => o.id === fieldValue.value);

                return (
                  <CustomInfoMultipleLine
                    key={field.id}
                    icon="icon-danxuan"
                    name={field.name}
                    value={
                      <div className="value radios">
                        {option && (
                          <span
                            key={option.id}
                            style={{
                              backgroundColor: option.color,
                              color: textColorMap[option.color],
                            }}
                            className="radio-tag"
                          >
                            {option.value}
                          </span>
                        )}
                      </div>
                    }
                  />
                );
              }
              // 多选
              case 4: {
                const options = field.property.options;
                const values = fieldValue.value || [];
                const selectedOptions = values
                  .map((v) => {
                    return options.find((o) => o.id === v);
                  })
                  .filter((i) => i);
                return (
                  <CustomInfoMultipleLine
                    key={field.id}
                    icon="icon-duoxuan"
                    name={field.name}
                    value={
                      <div className="value radios">
                        {selectedOptions.map((o) => {
                          return (
                            <span
                              key={o.id}
                              style={{
                                backgroundColor: o.color,
                                color: textColorMap[o.color],
                              }}
                              className="radio-tag"
                            >
                              {o.value}
                            </span>
                          );
                        })}
                      </div>
                    }
                  />
                );
              }
              // 日期
              case 5: {
                return (
                  <CustomInfoLine
                    key={field.id}
                    name={field.name}
                    icon="icon-calendar-2-line"
                    value={
                      <div>
                        <RenderTime value={`${fieldValue.value}`} />
                      </div>
                    }
                  />
                );
              }
              // 复选框
              case 7: {
                return (
                  <CustomInfoLine
                    key={field.id}
                    name={field.name}
                    icon="icon-fuxuankuang"
                    value={
                      <>
                        {fieldValue.value === "true" ? (
                          <span
                            style={{ color: "#6BC950" }}
                            className="iconfont icon-Checkbox_unselect1"
                          ></span>
                        ) : (
                          <span
                            style={{ color: "#8a909f" }}
                            className="iconfont icon-a-noCheckbox_unselect"
                          ></span>
                        )}
                      </>
                    }
                  />
                );
              }
              // 人员
              case 11: {
                const imgs = (fieldValue.value || []).map((u) => ({
                  src: getOssUrl(u.img || {}),
                  text: u.nickName,
                }));
                return (
                  <CustomInfoLine
                    key={field.id}
                    name={field.name}
                    icon="icon-chengyuan"
                    value={
                      <StackAvatars
                        maxLength={5}
                        showCount={imgs.length > 5}
                        imgs={imgs}
                      />
                    }
                  />
                );
              }
              // 超链接
              case 15: {
                return (
                  <CustomInfoMultipleLine
                    key={field.id}
                    icon="icon-link1"
                    name="超链接"
                    value={
                      fieldValue?.value?.link && (
                        <div
                          className="value"
                          style={{
                            wordWrap: "break-word",
                          }}
                        >
                          <a
                            style={{ color: "#3972F9" }}
                            href={fieldValue?.value?.link}
                          >
                            {fieldValue?.value?.link}
                          </a>
                        </div>
                      )
                    }
                  />
                );
              }
              // 附件
              case 17: {
                return (
                  <CustomInfoMultipleLine
                    key={field.id}
                    icon="icon-attachment-line"
                    name={field.name}
                    value={
                      <div className="value">
                        {(fieldValue?.value || []).map((file) => {
                          return (
                            <Attachment
                              key={file.id}
                              onClick={() =>
                                onAttachmentClick && onAttachmentClick(file)
                              }
                              thumbnail={file.thumbnail}
                              fieldType={file.fileType}
                              name={file.name}
                              username={file.creator.nickName}
                            />
                          );
                        })}
                      </div>
                    }
                  />
                );
              }
              // 单项关联
              case 23: {
                return (
                  <CustomInfoMultipleLine
                    key={field.id}
                    icon="icon-guabnlian"
                    name={field.name}
                    value={
                      <div className="value associate">
                        {(fieldValue.value || []).map((item) => {
                          return (
                            <span key={item.id} className="square-tag">
                              {item.name}
                            </span>
                          );
                        })}
                      </div>
                    }
                  />
                );
              }
            }
          })}
      </Accordion>
    </>
  );
};

const Index = () => {
  const router = useRouter();
  const {
    spaceId = "",
    channelId = "",
    recordId = "",
    listingId = "",
    confirmId = "",
    channelName = "",
  } = router.params || {};
  /** 0 任务详情， 1 确认详情 */
  const [pageType, setPageType] = useState(0);
  const wrapperRef = useRef<HTMLDivElement>(null);
  /** 切换状态的抽屉 */
  const [taskStatusOpen, setTaskStatusOpen] = useState(false);
  /** 切换任务阶段 */
  const [phaseListOpen, setPhaseListOpen] = useState(false);
  /** 确认或驳回弹窗 */
  const [checkConfirmOpen, setCheckConfirmOpen] = useState(false);
  const [confirmStatus, setConfirmStatus] = useState(true);
  /** 确认或驳回的 文字 */
  const [confirmText, setConfirmText] = useState("");
  /** 当前查看的信息 */
  const [detail, setDetail] = useState<
    ITaskDetailResponse | IFileCheckDetail | undefined
  >();
  /** 确认项列表，前后切换 */
  const [listingList, setListingList] = useState<IListingConfirm[]>([]);
  /** 缓存的列表detail */
  const listingListDetailRef = useRef<
    (ITaskDetailResponse | IFileCheckDetail)[]
  >([]);
  /** 在确认项的序号 */
  const [currentListIdx, setCurrentListIdx] = useState(0);
  /** 序号 */
  const currentIdxRef = useRef(0);
  /** 输入框是否聚焦 */
  const [confirmFocus, setConfirmFocus] = useState(false);
  /** 任务阶段 - options */
  const [phaseList, setPhaseList] = useState<ITaskPhase[]>([]);
  /** 单独附件 */
  const [attachment, setAttachment] = useState<ITaskAttachment[]>([]);
  /** 子任务数据 */
  const [subTasks, setSubTasks] = useState<ISubTaskResponse>();
  /** 评论 */
  const [comments, setComments] = useState<ITaskComment[]>([]);
  /** 确认记录 */
  const [records, setRecords] = useState<IListing[]>([]);
  useState(() => {
    if (!(confirmId && listingId)) {
      // 任务详情，修改title
      document.title = channelName;
    }
  });

  /** 跳到确认日志 */
  const handleJumpLog = () => {
    Taro.navigateTo({
      url: `/pages/project-check-log/index?spaceId=${spaceId}&listingId=${listingId}&confirmId=${confirmId}`,
    });
  };

  /** 跳到子任务 */
  const handleJumpSubTask = (item: IChildren) => {
    Taro.navigateTo({
      url: `/pages/project-check-task/index?spaceId=${spaceId}&channelId=${channelId}&recordId=${item?.recordId}`,
    });
  };

  /** 确认或驳回 */
  const handleConfirm = async () => {
    Taro.showLoading();
    const cur = listingList[currentListIdx];
    const { code, data, message } = await confirmCheck(
      spaceId,
      listingId,
      cur.id,
      "",
      {
        confirmState: confirmStatus ? 1 : 2,
        content: `<p>${confirmText}</p>`,
      }
    );
    if (code !== 0) {
      Taro.hideLoading();
      alert(message);
      return;
    }
    Taro.hideLoading();
    setCheckConfirmOpen(false);
    const id = listingList[currentListIdx].id;
    getCheckTaskDetail(id);
  };
  /** 获取确认详情信息 */
  const getCheckTaskDetail = async (_id?: string) => {
    const id = _id || confirmId;
    const { code, data, message } = await fetchProjectTaskDetail(
      spaceId,
      listingId,
      id
    );

    if (code === 0) {
      // data.canConfirm = false;
      // data.confirmLogState = 2;
      setDetail(data);
      // 存入缓存
      listingListDetailRef.current[currentIdxRef.current] = data;
    } else {
      alert(message);
      return;
    }
  };

  /** 上/下 一个确认项 */
  const handlePageChange = debounce(async (prev: boolean = true) => {
    if (listingList.length <= 1) return;
    const nextIdx = prev ? currentListIdx - 1 : currentListIdx + 1;
    if (nextIdx < 0 || nextIdx > listingList.length - 1) return;
    const nextConfirmId = listingList[nextIdx].id;
    setCurrentListIdx(nextIdx);
    currentIdxRef.current = nextIdx;
    if (listingListDetailRef.current[nextIdx]) {
      // 读取缓存
      setDetail(listingListDetailRef.current[nextIdx]);
      return;
    }
    getCheckTaskDetail(nextConfirmId);
  }, 100);

  /** 修改阶段 */
  const handleChangePhase = async (phase: ITaskPhase) => {
    const oldId = getvalueFromFields(
      "61ce9a6acf529c341c7ef8d4",
      detail?.fieldValues
    )?.id;
    if (phase.id === oldId) {
      return;
    }
    Taro.showLoading();
    const { code, data, message } = await modifyTaskPhase(
      spaceId,
      channelId,
      "default",
      recordId,
      {
        oldPhaseId: oldId,
        phaseId: phase.id || "",
      }
    );
    if (code !== 0) {
      alert(message);
      return;
    }
    setPhaseListOpen(false);
    updateDetail();
  };
  /** 任务详情，修改字段后修改detail */
  const updateDetail = async () => {
    const { code, data, message } = await fetchTaskDetail(
      spaceId,
      channelId,
      "default",
      recordId
    );
    if (code !== 0) {
      alert(message);
      return;
    }
    Taro.hideLoading();
    setDetail(data);
  };
  /** 修改状态 */
  const handleChangeStatus = async (option) => {
    if (detail?.fieldValues.stateId === option.id) {
      return;
    }
    const { code, data, message } = await updateTaskStatus(spaceId, channelId, {
      recordId: recordId,
      fieldId: "61ce9a6acf529c341c7ef8d1",
      fieldType: 3,
      value: option.id,
    });
    setTaskStatusOpen(false);
    if (code !== 0) {
      alert(message);
      return;
    } else {
      updateDetail();
    }
  };
  const handleAttachmentClick = (file: FileItem) => {
    // 预览
    const type = matchSuffixType(file.extensionName, file.type);

    Taro.navigateTo({
      url: `/pages/file-preview/index?spaceId=${spaceId}&channelId=${
        file.channelId
      }&fileId=${file.fileId}&canPreview=${!!type}`,
    });
  };
  /** 获取sts token */
  const initToken = async () => {
    try {
      const { code, data, message } = await fetchDetailStsToken(spaceId);
      localStorage.setItem("stsToken", JSON.stringify(data));
    } catch (e) {}
  };
  useEffect(() => {
    const init = async () => {
      if (confirmId && listingId) {
        setPageType(1);
        Taro.showLoading();
        /** 确认详情 */
        const accessKey = Taro.getStorageSync("accessKey");
        const { code, data, message } = await fetchListingList(
          spaceId,
          listingId,
          accessKey
        );
        Taro.hideLoading();
        if (code === 0) {
          setListingList(data);
        } else {
          alert(message);
          return;
        }
        const idx = data.findIndex((item) => item.id === confirmId);
        setCurrentListIdx(idx);
        currentIdxRef.current = idx;
        getCheckTaskDetail();
      } else {
        /** 任务详情 */
        setPageType(0);
        Taro.showLoading();
        initToken();
        const [taskDetail, subTask, phaseRes, commontRes, recordRes] =
          await Promise.all([
            fetchTaskDetail(spaceId, channelId, "default", recordId),
            fetchSubTask(spaceId, channelId, "default", recordId),
            fetchPhaseList(spaceId, channelId),
            fetchTaskComment(spaceId, channelId, recordId),
            fetchTaskRecord(spaceId, recordId),
          ]);
        Taro.hideLoading();
        if (taskDetail.code !== 0) {
          alert(taskDetail.message);
          return;
        } else {
          setDetail(taskDetail.data);
          // 筛选出单独的附件
          const attachmentFields = taskDetail.data.fields.filter(
            (field) => field.fieldType === 17 && field.custom === false
          );
          let attachments: ITaskAttachment[] = [];
          attachmentFields.map((f) => {
            const values =
              (taskDetail.data.fieldValues?.data.find(
                (x) => x.fieldId === f.fieldId
              )?.value as ITaskAttachment[]) || [];
            attachments = attachments.concat(values);
          });
          setAttachment(attachments);
        }
        if (subTask.code !== 0) {
          alert(subTask.message);
          return;
        } else {
          setSubTasks(subTask.data);
        }
        if (phaseRes.code !== 0) {
          alert(phaseRes.message);
          return;
        } else {
          setPhaseList(phaseRes.data);
        }
        if (commontRes.code !== 0) {
          alert(commontRes.message);
          return;
        } else {
          setComments(commontRes.data);
        }
        if (recordRes.code !== 0) {
          alert(recordRes.message);
          return;
        } else {
          setRecords(recordRes.data);
        }
      }
    };
    init();
    window.scrollTo(0, 0);
  }, []);

  useEffect(() => {
    /** iframe类型，添加手势 */
    if (pageType !== 1) return;
    if (listingList[currentListIdx]?.originType !== "file") return;
    let hammer;
    setTimeout(() => {
      const iframe = document.getElementsByTagName("iframe")[0];
      if (!iframe) return;
      try {
        const body = iframe.contentWindow?.document.body;
        if (!body) return;
        // console.log(body);
        hammer = new Hammer(body);
        hammer.on("swipeleft", (e) => {
          handlePageChange(false);
        });
        hammer.on("swiperight", (e) => {
          handlePageChange(true);
        });
      } catch (e) {}
    }, 100);
    return () => {
      if (hammer) {
        hammer.off("swipeleft");
        hammer.off("swiperight");
      }
    };
  }, [listingList, currentListIdx, pageType, handlePageChange]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const hammer = new Hammer(wrapperRef.current);
    hammer.on("swipeleft", (e) => {
      handlePageChange(false);
    });
    hammer.on("swiperight", (e) => {
      handlePageChange(true);
    });
    return () => {
      hammer.off("swipeleft");
      hammer.off("swiperight");
    };
  }, [handlePageChange, listingList]);

  useEffect(() => {
    let editor;
    const initEditor = async () => {
      const dom = document.querySelector(".desc-editor") as HTMLElement;
      if (!dom) return;
      editor = await ClassicEditor.create(dom, {
        toolbar: false,
        isReadOnly: true,
      });
      editor.enableReadOnlyMode("editor-container");
    };
    initEditor();
    return () => {
      editor && editor.destroy && editor.destroy();
    };
  }, [detail]);

  useEffect(() => {
    if (taskStatusOpen || phaseListOpen) {
      (document.querySelector(".taro_page") as HTMLElement).style.overflow =
        "hidden";
      (document.querySelector(".taro_page") as HTMLElement).style.height =
        "100vh";
    } else {
      (document.querySelector(".taro_page") as HTMLElement).style.overflow =
        "scroll";
      (document.querySelector(".taro_page") as HTMLElement).style.height =
        "unset";
    }
  }, [taskStatusOpen, phaseListOpen]);
  return (
    <div
      ref={wrapperRef}
      className={classNames("project-check-task clearfix", {
        "file-preview": listingList[currentListIdx]?.originType === "file",
        hidden: taskStatusOpen || phaseListOpen,
      })}
    >
      <NavBar
        className="nav-bar"
        left={undefined}
        center={pageType === 0 ? "任务详情" : "确认详情"}
        right={
          pageType === 0 ? (
            <></>
          ) : (
            <span
              className="iconfont icon-querenrizhi"
              onClick={handleJumpLog}
            ></span>
          )
        }
        fixed
      ></NavBar>
      {pageType === 1 && (
        <AtTabs
          swipeable={false}
          className="m-tabs"
          current={currentListIdx}
          scroll
          tabList={listingList.map((l) => ({ title: l.id }))}
          onClick={(idx) => handlePageChange(currentListIdx > idx)}
        >
          {listingList.map((listing, idx) => {
            // 不是当前tab，返回空
            if (
              !detail ||
              idx !== currentListIdx ||
              (listing.originType === "task" && !detail.fields)
            ) {
              return (
                <AtTabsPane key={idx} current={idx} index={idx}></AtTabsPane>
              );
            }
            // 文件类型，返回预览组件
            if (listing.originType === "file") {
              return (
                <AtTabsPane key={idx} current={idx} index={idx}>
                  <PreviewComponent key={Math.random()} file={detail} />
                </AtTabsPane>
              );
            }
            // 确认项
            return (
              <AtTabsPane key={idx} current={idx} index={idx}>
                <>
                  <TabMainInfo
                    pageType={pageType}
                    detail={detail as ITaskDetailResponse}
                  />
                  {/* 占位，防止footer遮挡 */}
                  <div style={{ height: "52px" }}></div>
                </>
              </AtTabsPane>
            );
          })}
        </AtTabs>
      )}
      {/* 任务详情 */}
      {pageType === 0 && (
        <div className="task-container">
          <TabMainInfo
            pageType={pageType}
            onPhaseClick={() => setPhaseListOpen(true)}
            onStatusClick={() => setTaskStatusOpen(true)}
            onAttachmentClick={handleAttachmentClick}
            detail={detail as ITaskDetailResponse}
          />
          {subTasks && subTasks.children && subTasks.children.length > 0 && (
            <Accordion
              title={`子任务 · ${subTasks?.done}/${subTasks?.total}`}
              img="icon-task-grouping"
              className="sub-tasks"
              key={subTasks?.children || Math.random()}
              initClose
            >
              {(subTasks?.children || []).map((task: IChildren) => {
                const RenderSubTask = ({ item, level = 0 }) => {
                  const hasChild = !!item.children.length || level > 0;

                  const taskName = getvalueFromFields(
                    "61ce9a6acf529c341c7ef8c0",
                    item
                  );
                  const stateId = item?.stateId;
                  const status = item?.stateOptions?.find(
                    (opt) => opt.id === stateId
                  );
                  return (
                    <>
                      <div
                        className={classNames("sub-task", `level-${level}`, {
                          "multiple-line": hasChild,
                        })}
                        onClick={() => handleJumpSubTask(item)}
                      >
                        <div
                          className="left"
                          style={{
                            backgroundColor: status.color,
                          }}
                        ></div>
                        <div className="right ">
                          {hasChild
                            ? (() => {
                                const time = getvalueFromFields(
                                  "61ce9a6acf529c341c7ef8c8",
                                  item
                                );
                                const noTime =
                                  !time || time === "0" || time === "undefined";
                                const childCount = getTaskChildLength(item);
                                return (
                                  <>
                                    <div className="title">{taskName}</div>
                                    <div className="desc">
                                      {!noTime && (
                                        <span className="iconfont icon-a-calendar-event-lineover"></span>
                                      )}
                                      <RenderTime value={`${time}`} />
                                      {!noTime && !!childCount && <i />}
                                      {!!childCount && (
                                        <>
                                          <span className="iconfont icon-task-grouping"></span>
                                          {childCount}
                                        </>
                                      )}
                                    </div>
                                  </>
                                );
                              })()
                            : taskName}
                        </div>
                      </div>
                      {item.children.map((child) => {
                        return (
                          <RenderSubTask
                            key={child.recordId}
                            item={child}
                            level={level + 1}
                          />
                        );
                      })}
                    </>
                  );
                };
                return <RenderSubTask key={task.recordId} item={task} />;
              })}
            </Accordion>
          )}
          <Accordion
            title={`附件·${attachment.length}`}
            img="icon-attachment-1"
            className="attachments clearfix"
            key={Math.random()}
          >
            {attachment.map((c) => {
              return (
                <Attachment
                  key={c.id}
                  onClick={() => handleAttachmentClick(c)}
                  thumbnail={c.thumbnail}
                  fieldType={c.fileType}
                  name={c.name || ""}
                  username={c.creator?.nickName || ""}
                />
              );
            })}
          </Accordion>
          <Accordion
            title={`确认·${records.length}`}
            img="icon-send"
            className="checks"
            key={records.length || Math.random()}
          >
            {records.map((record) => {
              let names = (record.confirmedBys || []).map((i) => {
                if (i.nickName.length > 3) {
                  return i.nickName.substring(0, 3) + "...";
                }
                return i.nickName;
              });
              if (names.length > 4) {
                names = names.slice(0, 4);
                names.push(`+${names.length - 4}`);
              }
              const checker = (
                <>
                  {names.map((n) => {
                    return (
                      <span key={n} className="checker-name">
                        {n}
                      </span>
                    );
                  })}
                </>
              );
              return (
                <CheckItem
                  key={record.id}
                  onClick={() => {
                    Taro.navigateTo({
                      url: `/pages/project-check-detail/index?spaceId=${router.params.spaceId}&listingId=${record.id}`,
                    });
                  }}
                  name={record.name}
                  status={record.confirmState || 1}
                  sender={record.originator?.nickName || ""}
                  confirmType={record.confirmType}
                  checker={checker}
                  expired={dayjs(record.endDate).format("YYYY-MM-DD")}
                />
              );
            })}
          </Accordion>
          <Accordion
            title={`评论·${comments.length}`}
            img="icon-message-line"
            className="comments hide-last-comment-shadow"
            key={comments || Math.random()}
          >
            {comments.map((c) => {
              return (
                <TaskComment
                  key={c.id}
                  avatar={getOssUrl(c.img || {})}
                  name={c.nickName || ""}
                  time={dayjs(c.createdAt).format("MM-DD hh:mm")}
                  words={c.comment || ""}
                />
              );
            })}
          </Accordion>
          {/* 占位，防止footer遮挡 */}
          {/* <div style={{ height: "52px" }}></div> */}
        </div>
      )}
      {pageType === 1 &&
        detail &&
        !(detail.canConfirm === false && detail.confirmLogState === 0) && (
          <TaskFooter
            status={
              detail.canConfirm
                ? CheckStatusEnum.unCheck
                : detail.confirmLogState === 1
                ? CheckStatusEnum.check
                : CheckStatusEnum.notCheck
            }
            onCheck={() => {
              setConfirmStatus(true);
              setCheckConfirmOpen(true);
            }}
            onFail={() => {
              setConfirmStatus(false);
              setCheckConfirmOpen(true);
            }}
          />
        )}
      {pageType === 1 && listingList.length > 1 && (
        <div className="page-change">
          {currentListIdx !== 0 && (
            <div
              className="page-change-left"
              onClick={() => handlePageChange(true)}
            >
              <img src={pageLeft} />
            </div>
          )}
          {currentListIdx !== listingList.length - 1 && (
            <div
              className="page-change-right"
              onClick={() => handlePageChange(false)}
            >
              <img src={pageRight} />
            </div>
          )}
        </div>
      )}
      {isSafari() && !detail?.canConfirm && (
        <div
          className={classNames("bottom-div", {
            "bottom-50": true,
            "bottom-90":
              pageType === 1 &&
              detail &&
              !(detail.canConfirm === false && detail.confirmLogState === 0),
          })}
        ></div>
      )}
      <AtModal
        className="check-task-modal"
        isOpened={checkConfirmOpen}
        cancelText="取消"
        confirmText="确认"
        onClose={() => {
          setCheckConfirmOpen(false);
        }}
        onCancel={() => {
          setCheckConfirmOpen(false);
        }}
      >
        <AtModalContent>
          <div className="m-modal-header">
            {confirmStatus ? (
              <span
                style={{ color: CheckStatusColor.check }}
                className="iconfont icon-checkbox-circle-fill"
              ></span>
            ) : (
              <span
                style={{ color: CheckStatusColor.notCheck }}
                className="iconfont icon-daixiugai"
              ></span>
            )}
            {/* <img src={menuIcon} alt="" /> */}
            您已给出决定：【{confirmStatus ? "已确认" : "待修改"}】
          </div>
          <div className="m-modal-textarea">
            <AtTextarea
              count={false}
              value={confirmText}
              onChange={(text) => {
                setConfirmText(text);
              }}
              onFocus={() => {
                setConfirmFocus(true);
              }}
              onBlur={() => {
                setConfirmFocus(false);
              }}
              maxLength={200}
              placeholder={confirmFocus ? "" : "添加对您的决定的评论"}
            />
          </div>
          <div className="m-modal-footer">
            <Button
              className="cancel"
              onClick={() => {
                setCheckConfirmOpen(false);
              }}
            >
              取消
            </Button>
            <Button className="check" onClick={handleConfirm}>
              确定
            </Button>
          </div>
        </AtModalContent>
      </AtModal>
      <AtFloatLayout
        className="task-float-layout adapt-height"
        isOpened={taskStatusOpen}
        title=""
        onClose={() => {
          setTaskStatusOpen(false);
        }}
      >
        <div className="title">
          <img
            style={{
              visibility: "hidden",
            }}
            src={closeBlack}
          />
          状态
          <span
            className="iconfont icon-close"
            onClick={() => {
              setTaskStatusOpen(false);
            }}
          />
        </div>
        <div className="status">
          {detail?.fieldValues &&
            (detail?.fieldValues.stateOptions || []).map((option) => {
              return (
                <StatusLine
                  key={option.id}
                  name={option.value}
                  color={option.color}
                  onClick={() => handleChangeStatus(option)}
                  checked={detail?.fieldValues.stateId === option.id}
                />
              );
            })}
        </div>
      </AtFloatLayout>
      <AtFloatLayout
        className="task-float-layout adapt-height"
        isOpened={phaseListOpen}
        title=""
        onClose={() => {
          setPhaseListOpen(false);
        }}
      >
        <div className="title">
          <img
            style={{
              visibility: "hidden",
            }}
            src={closeBlack}
          />
          阶段
          <span
            className="iconfont icon-close"
            onClick={() => {
              setPhaseListOpen(false);
            }}
          />
        </div>
        <div className="status">
          {phaseList.map((phase) => {
            return (
              <StatusLine
                key={phase.id}
                name={phase.name || ""}
                color={phase.color}
                onClick={() => handleChangePhase(phase)}
                checked={
                  getvalueFromFields(
                    "61ce9a6acf529c341c7ef8d4",
                    detail?.fieldValues
                  )?.id === phase.id
                }
              />
            );
          })}
        </div>
      </AtFloatLayout>
    </div>
  );
};

export default Index;
